package com.zoffy.catdiarybackend.service.impl;

import cn.hutool.core.util.RandomUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.qcloud.cos.COSClient;
import com.qcloud.cos.exception.CosClientException;
import com.qcloud.cos.exception.CosServiceException;
import com.qcloud.cos.model.ObjectMetadata;
import com.qcloud.cos.model.PutObjectRequest;
import com.qcloud.cos.model.PutObjectResult;
import com.qcloud.cos.model.StorageClass;
import com.zoffy.catdiarybackend.common.BusinessException;
import com.zoffy.catdiarybackend.common.StateCode;
import com.zoffy.catdiarybackend.model.dto.user.UserInformationUpdateRequest;
import com.zoffy.catdiarybackend.model.dto.user.UserLoginRequest;
import com.zoffy.catdiarybackend.model.dto.user.UserRegistryRequest;
import com.zoffy.catdiarybackend.model.entity.User;
import com.zoffy.catdiarybackend.model.enums.user.UserRole;
import com.zoffy.catdiarybackend.model.enums.user.UserState;
import com.zoffy.catdiarybackend.model.vo.UserVo;
import com.zoffy.catdiarybackend.service.UserService;
import com.zoffy.catdiarybackend.mapper.UserMapper;
import jakarta.annotation.Resource;
import jakarta.servlet.http.Cookie;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;

/**
 * @author 86170
 * @description 针对表【user(用户)】的数据库操作Service实现
 * @createDate 2024-06-05 15:09:56
 */
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User>
        implements UserService {
    @Value("${application.secret.salt}")
    private String SALT;
    @Value("${tencent.bucket-name}")
    private String bucketName;
    @Resource
    private COSClient cosClient;
    @Autowired
    private RedisTemplate<Object, Object> redisTemplate;

    @Override
    public long userRegistry(UserRegistryRequest userRegistryRequest) {
        //非空校验
        String userAccount = userRegistryRequest.getUserAccount();
        String userPassword = userRegistryRequest.getUserPassword();
        String ensurePassword = userRegistryRequest.getEnsurePassword();
        if (StringUtils.isAnyBlank(userAccount, userPassword, ensurePassword)) {
            throw new BusinessException(StateCode.PARAMS_DELETION);
        }
        //账号密码长度限制
        if (userAccount.length() < 5 || userPassword.length() < 8) {
            throw new BusinessException(StateCode.PARAMS_ERROR, "账号密码长度过短");
        }
        //两次密码是否相同
        if (!userPassword.equals(ensurePassword)) {
            throw new BusinessException(StateCode.PARAMS_ERROR, "两次输入的密码不一致");
        }

        //判断账号是否存在
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("user_account", userAccount);
        User user = this.getOne(queryWrapper);
        if (user != null) {
            throw new BusinessException(StateCode.OPERATION_ERROR, "账号已存在");
        }
        //创建新用户
        User newUser = new User();
        newUser.setUserAccount(userAccount);
        newUser.setUserPassword(genSecret(userPassword));
        newUser.setUserProfile("该用户暂无简介");
        newUser.setUserAvatar("/defaultAvatar.png");
        newUser.setUserRole(UserRole.USER.getRole());
        newUser.setUserState(UserState.NORMAL.getState());
        this.save(newUser);
        return newUser.getId();
    }

    @Override
    public UserVo userLogin(HttpServletRequest request, UserLoginRequest userLoginRequest) {
        String userAccount = userLoginRequest.getUserAccount();
        String userPassword = userLoginRequest.getUserPassword();
        if (StringUtils.isAnyBlank(userAccount, userPassword)) {
            throw new BusinessException(StateCode.PARAMS_DELETION);
        }
        //验证登录
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("user_account", userAccount);
        queryWrapper.eq("user_password", genSecret(userPassword));
        User user = this.getOne(queryWrapper);
        if (user == null) {
            throw new BusinessException(StateCode.LOGIN_ERROR, "账号或密码错误");
        }


        //在Session中保存登录态
        UserVo userVo = UserVo.obj2Vo(user);

//        request.getSession().setAttribute(USER_INFO,userVo);
        redisTemplate.opsForValue().set(String.format("USER_%s", request.getSession().getId()), userVo);
//        response.addCookie(new Cookie("SessionId",""));
        return userVo;
    }

    @Override
    public void userLogout(HttpServletRequest request) {
        redisTemplate.delete(String.format("USER_%s", request.getSession().getId()));
    }

    @Override
    public UserVo getUserVo(HttpServletRequest request) {

        String sessionId = request.getSession().getId();
        return getUserVo(sessionId);
    }

    @Override
    public UserVo getUserVo(long id) {
        User user = this.getById(id);
        if (user == null) {
            return null;
        }
        return UserVo.obj2Vo(user);
    }

    @Override
    public UserVo getUserVo(String sessionId) {
        UserVo userVo = (UserVo) redisTemplate.opsForValue().get(String.format("USER_%s", sessionId));
        return userVo;
    }

    public String genSecret(String origin) {
        return DigestUtils.md5DigestAsHex((SALT + origin).getBytes());
    }

    @Override
    public boolean updateUserAvatar(HttpServletRequest request, MultipartFile file) throws IOException {
        UserVo userVo = getUserVo(request);
        if (userVo == null) {
            throw new BusinessException(StateCode.NOT_LOGIN_ERROR);
        }


        // 对象键(Key)是对象在存储桶中的唯一标识。
        String key = "/avatar-" + userVo.getId() + RandomUtil.randomString(5);


        InputStream inputStream = file.getInputStream();
        ObjectMetadata objectMetadata = new ObjectMetadata();
        PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, key, inputStream, objectMetadata);
        // 设置存储类型（如有需要，不需要请忽略此行代码）, 默认是标准(Standard), 低频(standard_ia)
        // 更多存储类型请参见 https://cloud.tencent.com/document/product/436/33417
        putObjectRequest.setStorageClass(StorageClass.Standard);

        try {
            PutObjectResult putObjectResult = cosClient.putObject(putObjectRequest);
            System.out.println(putObjectResult.getRequestId());
        } catch (CosServiceException e) {
            e.printStackTrace();
        } catch (CosClientException e) {
            e.printStackTrace();
        }


        User user = new User();
        user.setId(userVo.getId());
        user.setUserAvatar(key);
        return updateById(user);
    }

    @Override
    public boolean updateUserInformation(HttpServletRequest request, UserInformationUpdateRequest userInformationUpdateRequest) {
        UserVo userVo = getUserVo(request);
        if (userVo == null) {
            throw new BusinessException(StateCode.NOT_LOGIN_ERROR);
        }
        String userName = userInformationUpdateRequest.getUserName();
        if ("".equals(userName)) {
            throw new BusinessException(StateCode.PARAMS_ERROR, "昵称不能为空");
        }
        User user = new User();
        user.setId(userVo.getId());
        user.setUserName(userName);
        updateById(user);
        redisTemplate.opsForValue().set(String.format("USER_%s", request.getSession().getId()), userVo);
        return true;
    }
}




